#ifndef HANDTRACKER_HPP
#define HANDTRACKER_HPP

#include "HandInterface.hpp"

class HandTracker : public AbstractHandTracker {
public:
	static AbstractHandTracker* init( float meanshiftWeightFactor, float processNoiseCovScalar, float measurementNoiseCovScalar,
									 float shortDistIgnoreThreshold, cv::Rect trackingRect, cv::Mat& initImage, cv::Ptr< Segmenter > segmenter );
	
	static AbstractHandTracker* init( float meanshiftWeightFactor, float processToMeasurementNoiseRatio,
									 float shortDistIgnoreThreshold, cv::Rect trackingRect, cv::Mat& initImage, cv::Ptr< Segmenter > segmenter );

	HandTracker( float meanshiftWeightFactor, float shortDistIgnoreThreshold, cv::Rect trackingRect,
				cv::Ptr< Segmenter > segmenter, float measurementNoiseCovScalar );
	
	void initCornersAndKF( float processNoiseCovScalar, cv::Mat& initImage );
	
	cv::Rect track( cv::Mat& nextImage );
	cv::Rect track( cv::Mat& nextImage, cv::Rect& forbiddenRect );
	
protected:
	cv::Rect trackingRect;
	cv::Mat imgA;
	cv::Mat imgB;
	
	cv::Ptr< Segmenter > segmenter;
	
	cv::Mat* imgPtr1;
	cv::Mat* imgPtr2;
	
	cv::KalmanFilter positionKF;
	
	float prevX;
	float prevY;
	
	vector<cv::Point2f> corners;

	//FIX : Test these values //FULLTEST
	int maxCorners;
	int minCornersToTrack;
	double qualityLevel;
	double minDistance;
	
	float meanshiftWeightFactor;
	
	float cornerReuseErrorThreshold;
	
	float shortDistIgnoreThreshold; //FIXNOW should be scale dependent? //FULLTEST
	float accelerationIgnoreThreshold;
		
	float measurementNoiseCovScalar;
	
	HandTracker( bool useHSV, float meanshiftWeightFactor, float shortDistIgnoreThreshold, cv::Rect trackingRect,
				cv::Ptr< Segmenter > segmenter, float measurementNoiseCovScalar );
	
	cv::Rect track( cv::Mat& nextImage, cv::Rect& forbiddenRect, bool useForbiddenRect );
	
	void phaseOneUpdateAndRejection( cv::Size& frameSize, vector<cv::Point2f>& corners, vector<cv::Point2f>& nextCorners,
								   vector<uchar>& cornersFound, vector<float>& cornerErrors, vector<cv::Point2f>& phaseOneAcceptedCorners );
	
	void phaseTwoUpdateAndRejection( cv::Size& frameSize, vector<cv::Point2f>& inputCorners, vector<cv::Point2f>& outputCorners );
	
	void addMoreCorners( vector<cv::Point2f>& corners );
};

#endif
	
	
	